package com.mew.chess.core.game.shbz.game;

import cn.hutool.core.util.RandomUtil;
import com.mew.chess.core.game.shbz.game.common.FishConstantValue;
import com.mew.chess.core.game.shbz.game.common.FishLinkType;
import com.mew.chess.core.game.shbz.game.task.FishPushCycleScheduleTask;
import com.mew.chess.core.game.shbz.game.task.FishScheduleTask;
import com.mew.chess.core.game.shbz.game.task.TideScheduleTask;
import com.mew.chess.core.game.shbz.service.ShbzService;
import com.mew.common.config.SpringContextBean;
import com.mew.common.dc.redis.FishingRedisService;
import com.mew.common.entity.config.FishingFish;
import com.zebra.common.concurrent.ZebraExecutorManager;
import com.zebra.common.concurrent.ZebraScheduler;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@Data
@Slf4j
public class ShbzScheduleManager {

    private AtomicBoolean flag = new AtomicBoolean(false);

    private int roomId;
    private int tableId;

    private ZebraScheduler zebraScheduler;
    private ExecutorService executorService;

    private ScheduledFuture<?>  fishScheduledFuture;
    private ScheduledFuture<?>  fishScheduledFutureCycle;//普通鱼时间轮
    private ScheduledFuture<?>  tideScheduledFuture;//鱼潮时间轮
    private ScheduledFuture<?>  sleepScheduledFuture;//鱼潮时间轮

    private ScheduledFuture<?>  goldScheduledFuture;//金币持久化

    private FishScheduleTask fishScheduleTask;
    private FishPushCycleScheduleTask fishPushCycleScheduleTask;
    private TideScheduleTask tideScheduleTask;

    private ShbzService shbzService;


    public ShbzScheduleManager(int tableId, int roomId){

        this.roomId = roomId;
        this.tableId = tableId;

        zebraScheduler = null == zebraScheduler ? ZebraExecutorManager.getInstance().getDefaultScheduler() : zebraScheduler;
        executorService = null == executorService ? ZebraExecutorManager.getInstance().getDefaultExecutor() : executorService;
    }

    public void start(){
        if(flag.compareAndSet(false, true)){
            initializeTask();
            prepareStartTimer();
        }
    }

    public void stop(){
        try {
            zebraScheduler.cancelScheduled(fishScheduledFuture);
        } catch (Exception e) {
        }
        stopCycle();

        //结算
        shbzService.payment(roomId,tableId);
        try {
            ZebraScheduler.cancelScheduled(goldScheduledFuture);
        } catch (Exception e) {
        }
        flag.getAndSet(false);
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTable(tableId);
        table.getFishMap().clear();
        table.getFishKeyId().set(1);
        shbzService.tableLog(table);
    }

    private void prepareStartTimer(){
        log.info("---Fish Prepare StartTimer：roomId {}", this.getRoomId());
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTable(tableId);
        table.setLinkType(FishLinkType.Prepare.code());
        table.setStartTime(System.currentTimeMillis());
        table.setRuleTime(FishConstantValue.PREPARE_TIME);
        goldScheduledFuture = zebraScheduler.scheduleWithFixedDelay(()->{shbzService.payment(roomId,tableId);stopTide();}, 600L, FishConstantValue.PAYMENT_TIME, TimeUnit.MILLISECONDS, executorService);
        fishScheduledFuture = zebraScheduler.schedule((this::startGame), FishConstantValue.PREPARE_TIME, TimeUnit.MILLISECONDS, executorService);
    }

    private void initializeTask(){

        Map<Integer, FishingFish> fish = ShbzGameManager.getInstance().getFish();
        if (null==fish||fish.isEmpty()){
            FishingRedisService fishingRedisService = SpringContextBean.getBean(FishingRedisService.class);
            ShbzGameManager.getInstance().putFishs(fishingRedisService.findFish());
        }

        if (null==fishScheduleTask){
            fishScheduleTask = SpringContextBean.getBean(FishScheduleTask.class);
        }
        if (null== fishPushCycleScheduleTask){
            fishPushCycleScheduleTask = SpringContextBean.getBean(FishPushCycleScheduleTask.class);
        }
        if (null== tideScheduleTask){
            tideScheduleTask = SpringContextBean.getBean(TideScheduleTask.class);
        }

        if (null==shbzService){
            shbzService = SpringContextBean.getBean(ShbzService.class);
        }
    }

    //-----------start fish-------------------------
    public void startGame(){

        stopCycle();
        if (!fishScheduleTask.fishCycle(roomId,tableId)){
            stop();
            log.info("stopCycle()");
            return;
        }

        log.info("---Fish start ：roomId {}", this.getRoomId());
        fishScheduledFutureCycle = zebraScheduler.scheduleWithFixedDelay((this::doFishCycle), 600L, FishConstantValue.fishRedisValue.fish_timer, TimeUnit.MILLISECONDS, executorService);
        sleepScheduledFuture = zebraScheduler.schedule(this::sleep, FishConstantValue.fishRedisValue.fish_timer_cycle, TimeUnit.MILLISECONDS, executorService);
    }

    public void sleep(){
        stopFishCycle();

        tideScheduledFuture = zebraScheduler.schedule(this::startTide, FishConstantValue.FISH_REST, TimeUnit.MILLISECONDS, executorService);
    }

    private void doFishCycle(){
        fishPushCycleScheduleTask.fishCycle(roomId,tableId,fishScheduledFutureCycle);
    }

    private void startTide(){
        stopSleepCycle();
        int type = RandomUtil.randomInt(FishConstantValue.TIDE_TYPE);
        if (!tideScheduleTask.fishCycle(roomId,tableId,type+101)){
            stop();
            return;
        }
        log.info("---Fish tide ：roomId {}", this.getRoomId());
        fishScheduledFuture = zebraScheduler.schedule((this::startGame), FishConstantValue.FISH_TIDE_CYCLE[type], TimeUnit.MILLISECONDS, executorService);
    }

    public void stopTide(){
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTable(tableId);
        if (table.getLinkType()>100 && table.getFishMap().isEmpty()){
            //没鱼了停止鱼潮
            log.info("没鱼了停止鱼潮");
            startGame();
        }
    }


    private void stopFishCycle(){
        try {
            zebraScheduler.cancelScheduled(fishScheduledFutureCycle);
        }catch (Exception e){
        }
    }
    private void stopTideCycle(){
        try {
            zebraScheduler.cancelScheduled(tideScheduledFuture);
        }catch (Exception e){
        }
    }
    private void stopSleepCycle(){
        try {
            zebraScheduler.cancelScheduled(sleepScheduledFuture);
        }catch (Exception e){
        }
    }
    private void stopCycle(){
        stopFishCycle();
        stopTideCycle();
        stopSleepCycle();
    }

}
